﻿/*
 *  XTL - XNA Tool Library, a collection with usefull XNA classes
 * 
 *  Copyright (C) 2009 Sebastian Schäfer
 * 
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */
using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace XTL.Models
{
    /// <summary>
    /// An attribute struct that stores:
    /// - Vertexposition
    /// - Texturecoordinate
    /// - Notmal
    /// - Tangent
    /// - Bitangent
    /// </summary>
    [Serializable]
    public struct VertexPosTexNormalTanBitan
    {
        private Vector3 pos;
        private Vector2 tex;
        private Vector3 normal, tan, bitan;

        #region Properties
        /// <summary>
        /// Vertexposition
        /// </summary>
        public Vector3 Position { get { return pos; } set { pos = value; } }
        /// <summary>
        /// Normal
        /// </summary>
        public Vector3 Normal { get { return normal; } set { normal = value; } }
        /// <summary>
        /// Texturecorodinate
        /// </summary>
        public Vector2 Tex { get { return tex; } set { tex = value; } }
        /// <summary>
        /// Tangent
        /// </summary>
        public Vector3 Tan { get { return tan; } set { tan = value; } }
        /// <summary>
        /// Bitangent
        /// </summary>
        public Vector3 Bitan { get { return bitan; } set { bitan = value; } }
        #endregion

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="position">Position</param>
        /// <param name="uv">Texturecoordinate</param>
        /// <param name="normal">Normal</param>
        /// <param name="tan">Tangent</param>
        /// <param name="bitan">Bitangent</param>
        public VertexPosTexNormalTanBitan(Vector3 position,Vector2 uv,Vector3 normal,Vector3 tan,Vector3 bitan)
        {
            pos = position;
            tex = uv;
            this.normal = normal;
            this.tan = tan;
            this.bitan = bitan;
        }

        /// <summary>
        /// Calculate the size in bytes
        /// </summary>
        public static int SizeInBytes { get { return sizeof(float) * 14; } }
        
        /// <summary>
        /// Create a new VertexElement array
        /// </summary>
        public static readonly VertexElement[] VertexElements =
        new VertexElement[] { 
            new VertexElement(0,0,VertexElementFormat.Vector3,
                VertexElementMethod.Default,VertexElementUsage.Position,0),
            new VertexElement(0,sizeof(float)*3,VertexElementFormat.Vector2,
                VertexElementMethod.Default,VertexElementUsage.TextureCoordinate,0),
            new VertexElement(0,sizeof(float)*5,VertexElementFormat.Vector3,
                VertexElementMethod.Default,VertexElementUsage.Normal,0),
            new VertexElement(0,sizeof(float)*8,VertexElementFormat.Vector3,
                VertexElementMethod.Default,VertexElementUsage.Tangent,0),
            new VertexElement(0,sizeof(float)*11,VertexElementFormat.Vector3,
                VertexElementMethod.Default,VertexElementUsage.Binormal,0),                
        };

        /// <summary>
        /// Create a human readable string
        /// </summary>
        /// <returns>Position</returns>
        public override string ToString()
        {
            return string.Format("{0},{1},{2}", pos.X, pos.Y, pos.Z);
        }

        /// <summary>
        /// Bake element arrays to a struct array
        /// </summary>
        /// <param name="pos">Position array</param>
        /// <param name="uv">Texturecoordinate array</param>
        /// <param name="normal">Normal array</param>
        /// <param name="tan">Tangent array</param>
        /// <param name="bitan">Bitangent array</param>
        /// <returns>Array</returns>
        public static VertexPosTexNormalTanBitan[] Bake(Vector3[] pos, Vector2[] uv, Vector3[] normal, Vector3[] tan, Vector3[] bitan)
        {
            int count = pos.Length;
            VertexPosTexNormalTanBitan[] res = new VertexPosTexNormalTanBitan[count];
            for (int idx = 0; idx < count; idx++)
                res[idx] = new VertexPosTexNormalTanBitan(pos[idx], uv[idx], normal[idx], tan[idx], bitan[idx]);
            return res;
        }
    }
}